import test_framework.test.unit.TestCase;
import mx.utils.Delegate;

import gugga.sequence.TaskManager;
import gugga.sequence.FictiveTask;
import gugga.sequence.ExecuteAsyncMethodTask;
import gugga.common.EventDescriptor;

import guggaLibTests.support.TaskExecutionEvaluator;
import guggaLibTests.support.PauseResumeMethodsSequence;

import gugga.common.ITask;
import gugga.sequence.PreconditionsTask;
import gugga.sequence.PreconditionsManager;
import gugga.utils.DebugUtils;
import mx.events.EventDispatcher;
import gugga.debug.Debugger;

import gugga.sequence.SingleExecutionTask;
import test_framework.test.unit.info.AssertFalseInfo;
import gugga.debug.Assertion;

/**
 * @author stefan
 */
class guggaLibTests.SingleExecutionTaskTest extends TestCase 
{
	private var delayInterval:Number = 1000;
	
	public function SingleExecutionTaskTest ()
	{
		super();

		this.delayInterval = 1000;
	}
	
	public function testConstructor ()
	{
		var actualTask : ITask = new FictiveTask();
		var task : ITask = new SingleExecutionTask(actualTask);
		
		assertInstanceOf(
			"the constructor should return an instance of the SingleExecutionTask class",
			task,
			SingleExecutionTask
		);
	}
	
	public function testStartAndCompletion ()
	{
		var evaluator : TaskExecutionEvaluator = new TaskExecutionEvaluator(this);
		
		var actualTask : ITask = new FictiveTask();
		var task1 : ITask = new SingleExecutionTask(actualTask);
		
		task1.addEventListener("start", Delegate.create(evaluator, evaluator.onTaskStarted));
		task1.addEventListener("completed", Delegate.create(evaluator, evaluator.onTaskCompleted));
		
		evaluator.registerRequiredTaskStatus( {task: task1, event: "start"} );		
		evaluator.registerRequiredTaskStatus( {task: task1, event: "completed"} );
		
		task1.start();
		
		evaluator.evaluateTaskExecution();
		evaluator.assertTaskStatusRegisterEqualsRequiredTaskStatusRegister("registered task statuses doesn't match the required ones");		
	}
	
	public function testSingleExecution ()
	{
		var evaluator : TaskExecutionEvaluator = new TaskExecutionEvaluator(this);
		
		var actualTask : ITask = new FictiveTask();
		var task : ITask = new SingleExecutionTask(actualTask);
		
		task.addEventListener("start", Delegate.create(evaluator, evaluator.onTaskStarted));
		task.addEventListener("completed", Delegate.create(evaluator, evaluator.onTaskCompleted));
		
		var firstBlock = function ()
		{
			evaluator.registerRequiredTaskStatus( {task: task, event: "start"} );		
			evaluator.registerRequiredTaskStatus( {task: task, event: "completed"} );
			
			task.start();			
		}; 
		
		var secondBlock = function ()
		{
			evaluator.evaluateTaskExecution();
			evaluator.assertTaskStatusRegisterEqualsRequiredTaskStatusRegister("registered task statuses doesn't match the required ones");
			
			evaluator.registerRequiredTaskStatus({task: task, event: "completed"});
			
			task.start();
		};
		
		var thirdBlock = function ()
		{
			evaluator.evaluateTaskExecution();
			evaluator.assertTaskStatusRegisterEqualsRequiredTaskStatusRegister("the single execution task should not be able to start any more");
		};
		
		var pauseAndResumer : PauseResumeMethodsSequence = new PauseResumeMethodsSequence(
			this, 
			1000,
			[firstBlock,
			secondBlock,
			thirdBlock]
		);
		pauseAndResumer.start();
	}
	
	public function testIsRunning ()
	{
		var eventSource : ITask = new FictiveTask();
		var eventSourceDescriptor : EventDescriptor = new EventDescriptor(eventSource, "completed");
		var asyncTask : ITask = ExecuteAsyncMethodTask.create(
			eventSourceDescriptor,
			this,
			emptyMethod,
			null
		);
		var singleExecutionTask : ITask = new SingleExecutionTask(asyncTask);
		
		assertFalse(
			"the task should not be running",
			singleExecutionTask.isRunning()
		);
		
		singleExecutionTask.start();
		
		assertTrue(
			"the task should be running",
			singleExecutionTask.isRunning()
		);
		
		var firstBlock = function ()
		{		
			eventSource.start();
		};

		var obj = this;

		var secondBlock = function ()
		{
			obj.assertNotRunning(singleExecutionTask);
		};
		
		var pauseAndResumer : PauseResumeMethodsSequence = new PauseResumeMethodsSequence(
			this,
			1000,
			[firstBlock,
			secondBlock]
		);
		pauseAndResumer.start();
	}
	
	private function assertNotRunning(task)
	{
		assertFalse(
			"the task should not be running after completion",
			task.isRunning()			
		);
	}
	
	private function emptyMethod()
	{
		//
	}
}
	